package person.twj.session.core.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import person.twj.session.core.security.handler.MyLoginSuccessHandler;
import person.twj.session.core.security.handler.MyLogoutSuccessHandler;
import person.twj.session.core.security.handler.MyNotLoginAccessHandler;

@Configuration
//@EnableWebSecurity // 开启springSecurity自定义配置，在springboot项目中，可以省略该注解，因为它自动引入了该注解
public class WebSecurityConfig {
	@Bean
	public  PasswordEncoder passwordEncoder( ){
		return  new BCryptPasswordEncoder();
	}


	@Bean
	public UserDetailsService userDetailsService() {
		return new MyUserDetailsService();
	}



	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http.authorizeHttpRequests(
				authorize -> authorize
						// 禁止使用 /**
						// 放开不用认证的请求

						.requestMatchers("/login","/notLogin").permitAll()
						.anyRequest()
						//已认证的请求会被自动授权
						.authenticated()



				)
				.sessionManagement(sessionManagementCustomizer->{
//					用户登录成功后，信息保存在服务器Session中。SpringSecurity提供了4种方式控制会话创建。
//					* always：如果一个会话尚不存在，将始终创建一个会话。
//					* ifRequired：仅在需要时创建会话，默认。
//					* never：框架永远不会创建会话本身，但如果它已经存在，它将使用一个。
//					* stateless：不会创建或使用任何会话，完全无状态。
					sessionManagementCustomizer.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
				})


		;

		http.formLogin((formLogin) ->
						formLogin
								.usernameParameter("username")
								.passwordParameter("password")
								.loginPage("/login")	// 登录页
								.failureUrl("/login?failed")	//登录失败跳转页
								.successHandler(new MyLoginSuccessHandler())


		);

		http.logout(logout->{
			logout.logoutSuccessHandler(new MyLogoutSuccessHandler()); // 退出登录成功 handler
		});

		http.addFilterBefore(new WelcomeFilter("/","/login"), UsernamePasswordAuthenticationFilter.class);

		http.exceptionHandling(exception->{
			exception.authenticationEntryPoint(new MyNotLoginAccessHandler());// 请求未认证的处理
		});
		// 关闭”crsf攻击“防御 ,登录时会带参数crsf
//		http.csrf(csrf -> csrf.disable());
		// 开启跨域访问限制或禁用跨域访问限制
//		http.cors(cors->cors.disable());// 禁用跨域访问限制



		return http.build();

	}
}